var http = require('http');
var path = require('path');
var url = require('url');
var fs = require('fs');
var urlencode = require('urlencode');

var log4js = require('log4js');
log4js.configure(path.resolve(process.argv[1], '../loggerConfig.json'),{});

var serverConfig = JSON.parse(fs.readFileSync(path.resolve(process.argv[1], '../serverConfig.json'), "utf8"));
var PORT = serverConfig.port || 80;
var ROOT = path.resolve(serverConfig.root || path.join(process.argv[1], '../root'));
var BUFFSIZE = serverConfig.buffsize || 1024*1024;
var LOGGERLEVEL = serverConfig.loggerlevel || 'INFO';

var logger = log4js.getLogger();
logger.setLevel(LOGGERLEVEL);

function httpProcess(request, response){
	var pathname = urlencode.decode(url.parse(request.url).pathname, 'utf8');
	var file = path.join(ROOT, pathname);
	
	fs.exists(file, function(exists){
		if(exists){
			fs.stat(file, function(err, stats){
				if(stats.isDirectory()){
					logger.info('200 LIST ' + request.connection.remoteAddress + ' ' + pathname);
					generateContentHTML(pathname, file, response);
				} else if(stats.isFile()) {
					logger.info('200 DOWN ' + request.connection.remoteAddress + ' ' + pathname);
					startTransfer(file, response);
				} else {
					response.writeHead(500, {
						'Content-Type': 'text/plain'
					});
					
					logger.info('500 ' + request.connection.remoteAddress + ' ' + file);
					response.write("Cannot download this file.");
					response.end();
				}
			});
		} else {
			response.writeHead(404, {
				'Content-Type': 'text/plain'
			});
			
			logger.info('404 ' + request.connection.remoteAddress + ' ' + file);
			response.write("This file or path is not exists.");
			response.end();
		}
	});
}

function startTransfer(file, response){
	response.writeHead(200, {
		'Content-Type': 'application/octet-stream',
		'Content-disposition': 'attachment'
	});
	var rs = fs.createReadStream(file, {'buffer':BUFFSIZE}).pipe(response);
}

function generateContentHTML(pathname, dir, response){
	response.writeHead(200, {
		'Content-Type': 'text/html'
	});
	fs.readdir(dir, function(err, fileList){
		var dirs=[];
		var files=[];
		(function next(i){
			if(i<fileList.length){
				fs.stat(path.join(dir,fileList[i]), function(err, stats){
					if(stats.isDirectory()){
						dirs.push(fileList[i]);
					} else {
						files.push([fileList[i],stats]);
					}
					next(i+1);
				});
			} else {
				getHTML(pathname, dirs, files, response);
			}
		}(0));
	});
}

function getHTML(pathname, dirs, files, response){
	response.write('<html><head><title>'+pathname+'</title><meta charset="utf-8"/></head><body>\n');
	response.write('<h1>'+pathname+'</h1>');
	response.write('<table><tr><td>Name</td><td>Size</td></tr>');
	if(pathname != '/'){
		response.write('<tr><td><a href="../">..</a></td>\n');
		response.write('<td>&lt;DIR&gt;</td></tr>\n');
	}
	for(var i=0; i<dirs.length; i++){
		response.write('<tr><td><a href="./'+urlencode(dirs[i], 'utf8')+'/">'+dirs[i]+'</a></td>\n');
		response.write('<td>&lt;DIR&gt;</td></tr>\n');
	}
	for(var i=0; i<files.length; i++){
		response.write('<tr><td><a href="./'+urlencode(files[i][0], 'utf8')+'">'+files[i][0]+'</a></td>\n');
		response.write('<td>'+files[i][1].size+'</td></tr>\n');
	}
	response.write('</table>');
	response.end('</body></html>');
}

var server = http.createServer(httpProcess);

server.listen(PORT);
console.log("Server running on port " + PORT);
console.log("Server root is " + ROOT);